﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using XRpgLibrary.Events;
using EyesOfTheDragon.Events;
using EyesOfTheDragon.Globals;

namespace EyesOfTheDragon.Components
{
    public class map :IDraw 
    {
        public static map Instance;
        public map()
        {
        }
        [XmlIgnore]
        public float MapScale = 1;
        [XmlIgnore]
        public int CurrentMap = 1;
        public Layer getLayer(string name)
        {
            foreach (Layer l in layer)
            {
                if (l.name == name)
                    return l;
            }
            return new Layer();
        }
        public Vector2 TotalWidthHeight
        {
            get 
            { 
                return new Vector2(width * tilewidth, height*tileheight);
            }
        }
        private float blinkElapsed = 0;
        private bool blinkOn = false;
        public void Draw(GameTime gt, SpriteBatch sp)
        {
            int numLayers = layer.Count;
            blinkElapsed += gt.ElapsedGameTime.Milliseconds / 1000f;
            if (blinkElapsed > .5f)
            {
                if (blinkOn)
                    blinkOn = false;
                else
                    blinkOn = true;
                blinkElapsed = 0;
            }
            for (int i = 0; i < numLayers; i++)
            {
                Layer l = layer[i];
                if (l.name == "triggersLayer")
                    continue;
                if (l.name == "blinkLayer")
                {
                    if (!blinkOn)
                        continue;
                    if (Anthem.Components.Player.Instance.PlayerLevel < map.Instance.CurrentMap)
                        continue;
                }
               
                List<GTile> gTile = l.data.tile;
                RectangleImage ri;
                foreach (GTile _tile in gTile)
                {
                    if (!_tile.Visible)
                        continue;
                    ri = SourceRectangles[_tile.gid];
                    sp.Draw(ri.texture, new Rectangle(_tile.Position.X, _tile.Position.Y, ri.rectangle.Width, ri.rectangle.Height), ri.rectangle, Color.White); 
                }
            }

        }
        static public map LoadFromXml(Game gr)
        {
            return LoadFromXml(gr, 1);
        }
        
        static public map LoadFromXml(Game gr, int lev)
        {
            SourceRectangles.Clear();
            TextureList.Clear();
            string house = "";
            if (lev > 1)
            {
                house = "House";
            }
            String _fileName = @"Content\XML\"+house+"Map" +lev+ ".xml";
            Stream stream = File.Open(_fileName, FileMode.Open, FileAccess.Read);
            XmlSerializer s = new XmlSerializer(typeof(map));
            map _ourMap = (map)s.Deserialize(stream);
            _ourMap.CurrentMap = lev;
            Instance = _ourMap;
            _ourMap.MapScale = _ourMap.tileheight / 64.0f;
            foreach (TileSet _tileSet in _ourMap.tileset)
            {
                if (_tileSet.image.source.IndexOf("Triggers") > 0)
                {
                    MapVariables.BaseTriggerGID = _tileSet.firstgid;
                }
                if (!TextureList.ContainsKey(_tileSet.firstgid))
                {
                    _tileSet.image.source = _tileSet.image.source.Remove(0, 3);
                    _tileSet.image.source = _tileSet.image.source.Remove(_tileSet.image.source.IndexOf("."), 4);
                    TextureList.Add(_tileSet.firstgid, gr.Content.Load<Texture2D>(@"" + _tileSet.image.source));
                }
            }
            foreach (Layer _layer in _ourMap.layer)
            {
                for (int i = 0; i < _layer.height * _layer.width; i++)
                {
                    int _gid = _layer.data.tile[i].gid;
                   
                    
                      //  continue;
                    int tilesetBuffer = 1;
                    for (int j = 0; j < _ourMap.tileset.Count;j++)
                    {
                        int a = (_ourMap.tileset[j].image.height / _ourMap.tileset[j].tileheight);
                        int b = (_ourMap.tileset[j].image.width / _ourMap.tileset[j].tilewidth);
                        int c = tilesetBuffer;
                        if (_gid >= a * b+c)
                        {
                            tilesetBuffer += (_ourMap.tileset[j].image.height / _ourMap.tileset[j].tileheight) * (_ourMap.tileset[j].image.width / _ourMap.tileset[j].tilewidth);
                        }
                        else
                        {
                            tilesetBuffer--;
                            _gid -= tilesetBuffer;
                            _gid--;
                            RectangleImage ri = new RectangleImage();
                            Rectangle r = new Rectangle();
                            _layer.data.tile[i].Position.X = (i % _ourMap.width) * _ourMap.tileset[j].tilewidth;
                            _layer.data.tile[i].Position.Y = (i / _ourMap.width) * _ourMap.tileset[j].tileheight;
                            _layer.data.tile[i].RectPosition = new Rectangle(_layer.data.tile[i].Position.X, _layer.data.tile[i].Position.Y, _ourMap.tilewidth, _ourMap.tileheight);
                            if (SourceRectangles.ContainsKey(_layer.data.tile[i].gid) || _layer.data.tile[i].gid == 0)
                                break;
                            r.Width = _ourMap.tileset[j].tilewidth;
                            r.Height = _ourMap.tileset[j].tileheight;
                            int xCount = _ourMap.tileset[j].image.width / _ourMap.tileset[j].tilewidth;
                            int yCount = _ourMap.tileset[j].image.height / _ourMap.tileset[j].tileheight;
                            r.X = _ourMap.tilewidth * (_gid % xCount);
                            r.Y = (_gid / yCount) * _ourMap.tileheight;
                            ri.rectangle = r;
                            ri.texture = TextureList[_ourMap.tileset[j].firstgid];
                            
                            SourceRectangles.Add(_layer.data.tile[i].gid, ri);
                            break;
                        }
                    }
                }
                
            }
            foreach (Layer _layer in _ourMap.layer)
                for (int i = 0; i < _layer.data.tile.Count; )
                {
                    int _gid = _layer.data.tile[i].gid;
                    if (_gid == 0)
                        _layer.data.tile.RemoveAt(i);
                    else
                    {
                        i++;
                    }
                }
            stream.Close();
            return _ourMap;
        }
        [XmlAttribute]
        public int width = 0;
        [XmlAttribute]
        public int height = 0;
        [XmlAttribute]
        public int tileheight = 0;
        [XmlAttribute]
        public int tilewidth = 0;
        [XmlAttribute]
        public string orientation = "";
        [XmlElement(Type = typeof(TileSet))]
        public List<TileSet> tileset = new List<TileSet>();
        [XmlElement(Type = typeof(Layer))]
        public List<Layer> layer = new List<Layer>();
        public static Dictionary<int, Texture2D> TextureList = new Dictionary<int, Texture2D>();
        public static Dictionary<int, RectangleImage> SourceRectangles = new Dictionary<int, RectangleImage>();
    }
   
    public class TilesMap
    {
        
       // public List<TileSet> tileset = new List<TileSet>();
       // public List<Layer> layer = new List<Layer>();
    }
    public class Layer
    {
        public GTile getTileByVector(Vector2 vec)
        {
            foreach (GTile tile in data.tile)
            {
                if (tile.Position.toVector() == vec)
                {
                    return tile;
                }
            }
            return null;
        }
        public List<GTile> getAllTiles()
        {
            if (data == null)
                return null;
            return data.tile;
        }
        public List<GTile> getTiles(int gid)
        {

            List<GTile> tiles = new List<GTile>();
            foreach (GTile t in data.tile)
            {
                if (t.gid == gid)
                    tiles.Add(t);
            }
            return tiles;
        }
        
        public Layer()
        {
        }
          [XmlAttribute]
        public int width = 0;
          [XmlAttribute]
        public int height = 0;
          [XmlAttribute]
        public string name = "";
          public Data data;
      //  public Data data;
    }
    public class Data
    {
        public Data()
        {
        }
         [XmlElement(Type = typeof(GTile))]
        public List<GTile> tile = new List<GTile>();
    }
    public class GTile
    {
        public GTile()
        {
        }
        [XmlAttribute]
        public int gid = 0;
        [XmlIgnore]
        public TwoPointInt Position = new TwoPointInt();
        [XmlIgnore]
        public Rectangle RectPosition = new Rectangle();
        [XmlIgnore]
        public bool Visible = true;
        
    }
    public class RectangleImage
    {
        public Texture2D texture;
        public Rectangle rectangle;
    }
    public class TwoPointInt
    {
        public int X = 0;
        public int Y = 0;
        public Vector2 toVector()
        {
            return new Vector2(X, Y);
        }
    }
    public class TileSet
    {
        public TileSet()
        {
        }
        [XmlAttribute]
        public int firstgid = 0;
        [XmlAttribute]
        public string name = "";
        [XmlAttribute]
        public int tileheight = 0;
        [XmlAttribute]
        public int tilewidth = 0;
        public TileImage image;

       
    }
    public class TileImage
    {
        public TileImage()
        {
        }
        [XmlAttribute]
        public string source = "";
        [XmlAttribute]
        public int width = 0;
        [XmlAttribute]
        public int height = 0;
    }
}
